package me.itsoo.artemis.framework.core.collect;

import java.io.Serializable;
import java.util.Iterator;
import java.util.StringJoiner;

/**
 * Kvs
 *
 * @author zxy
 * @version 0.0.1
 * @since 2023/5/1
 */
public class Kvs<K, V> implements Iterable<Kv<K, V>>, Serializable {

    private static final long serialVersionUID = 4815108722762326361L;

    @SuppressWarnings("rawtypes")
    private static final Kvs EMPTY = new EmptyKvs();

    private final Kv<K, V> head = Kv.empty();

    private Kv<K, V> curr;

    private int size;

    public Kvs() {
        this.curr = this.head;
        this.size = 0;
    }

    @SuppressWarnings("rawtypes")
    public static Kvs emptyKvs() {
        return EMPTY;
    }

    public void add(Kv<K, V> kv) {
        this.curr.setNext(kv);
        this.curr = this.curr.getNext();
        ++this.size;
    }

    public void addAll(Kvs<K, V> kvs) {
        kvs.forEach(this::add);
    }

    public int size() {
        return this.size;
    }

    public boolean isEmpty() {
        return (this == EMPTY) || (this.size == 0);
    }

    @Override
    public Iterator<Kv<K, V>> iterator() {
        return new Itr();
    }

    @Override
    public String toString() {
        final StringJoiner joiner = new StringJoiner(", ");
        this.forEach(t -> joiner.add(t.toString()));
        return "Kvs[" + joiner + ']';
    }

    /**
     * Itr
     */
    public class Itr implements Iterator<Kv<K, V>> {

        private Kv<K, V> itrCurr;

        public Itr() {
            this.itrCurr = Kvs.this.head;
        }

        @Override
        public boolean hasNext() {
            return this.itrCurr.getNext() != null;
        }

        @Override
        public Kv<K, V> next() {
            this.itrCurr = this.itrCurr.getNext();
            return this.itrCurr;
        }
    }
}
